
#include <QtCore>
#include <QtSql>

#include "Vorgaben.h"
#include "Datenverwaltung.h"

Datenverwaltung::Datenverwaltung(QObject *eltern) : QObject(eltern)
{
  K_Bereit=false;
  K_Datenbankversion=tr("unbekannt");
}
void Datenverwaltung::Laden()
{
  /* ist der SQLite Treiber da?*/
  if(!QSqlDatabase::isDriverAvailable("QSQLITE"))
  {
    emit Fehler(trUtf8("Das SQLite Modul von Qt ist nicht verfügbar."));
    return;
  }
  QString Datenbankdatei;
  QString Datenbankpfad;
#ifdef Q_WS_X11
  Datenbankpfad=QString("%1/.%2").arg(QDir::homePath()).arg(DB_VERZEICHNIS);
#else
  Datenbankpfad=QString("%1/%2").arg(QDir::homePath()).arg(DB_VERZEICHNIS);
#endif
  QDir Verzeichnis(Datenbankpfad);
  if(!Verzeichnis.exists())
  {
    if(!Verzeichnis.mkpath(Datenbankpfad))
    {
      emit Fehler(trUtf8("Das Verzeichnis %1 für die Datenbank konnte nicht angelegt werden.").arg(QDir::toNativeSeparators(Datenbankpfad)));
      return;
    }
  }
  Datenbankdatei=QString("%1/%2").arg(Datenbankpfad).arg(DB_DATEI);
  if(!QFile::exists(Datenbankdatei))
  {
    if(!DatenbankAnlegen(Datenbankdatei))
      return;
  }
  /*Dann mal alles mit Leben füttern*/
  if(!DatenbankOeffnen(Datenbankdatei))
    return;
  if(!ModelleLaden())
    return;
  emit Bereit();
}
bool Datenverwaltung::DatenbankOeffnen(const QString &datei)
{
  QSqlDatabase DB;
  if(!QSqlDatabase::contains(DB_VERBINDUNG))
    DB=QSqlDatabase::addDatabase("QSQLITE",DB_VERBINDUNG);
  else
    DB=QSqlDatabase::database(DB_VERBINDUNG);
  DB.setDatabaseName(datei);
  if(!DB.open())
  {
    emit Fehler(trUtf8("Die Datenbank konnte nicht geöffnet werden.\n%1").arg(DB.lastError().text()));
    return false;
  }
  return true;
}
bool Datenverwaltung::DatenbankAnlegen(const QString &datei)
{
  if(!DatenbankOeffnen(datei))
    return false;
  QSqlDatabase DB=QSqlDatabase::database(DB_VERBINDUNG,false);
  QSqlQuery Abfrage(DB);
  QStringList Tabellen;
  Tabellen<<DB_TABELLE_KATEGORIEN<<DB_TABELLE_POSTEN<<DB_TABELLE_VERSION;
  foreach(QString Tabelle,Tabellen)
  {
    if(!Abfrage.exec(Tabelle))
    {
      emit Fehler(tr("Die Tabelle %1 konnte nicht erstellt werden.\n%2").arg(Tabelle).arg(Abfrage.lastError().text()));
      DB.close();
      return false;
    }
  }
  if(!Abfrage.exec(QString("insert into Version Values(%1)").arg(DB_TABELLEN_VERSION)))
  {
    emit Fehler(tr("Konte die Versionsnummer der Datenbank nicht schreiben.\n%1").arg(Abfrage.lastError().text()));
    DB.close();
    return false;
  }
  DB.close();
  return true;
}
bool Datenverwaltung::ModelleLaden()
{
  QSqlDatabase DB=QSqlDatabase::database(DB_VERBINDUNG,false);
  QSqlQuery Abfrage(DB);
  if(!Abfrage.exec("select Version from Version;"))
  {
    emit Fehler(tr("Konnte die Versionsnummer der Datenbank nicht laden.\n%1").arg(Abfrage.lastError().text()));
    DB.close();
    return false;
  }
  if(!Abfrage.first())
  {
    emit Fehler(tr("Keine Versionsnummer in der Datenbank vorhanden."));
    DB.close();
    return false;
  }
  K_Datenbankversion=Abfrage.value(0).toString();
  K_Kategorien=new QSqlTableModel(this,DB);
  K_Posten=new QSqlRelationalTableModel(this,DB);
  K_Ausgaben=new QSqlTableModel(this,DB);

  K_Kategorien->setEditStrategy(QSqlTableModel::OnManualSubmit);
  K_Posten->setEditStrategy(QSqlTableModel::OnManualSubmit);
  K_Ausgaben->setEditStrategy(QSqlTableModel::OnManualSubmit);

  K_Kategorien->setTable("Kategorien");
  K_Posten->setTable("Posten");

  if(!K_Kategorien->select())
  {
    emit Fehler(tr("Konnte die Tabelle der Kategorien nicht lesen.\n%1").arg(K_Kategorien->lastError().text()));
    DB.close();
    return false;
  }
  K_Posten->setRelation(4,QSqlRelation("Kategorien","ID","Bezeichnung"));
  if((!K_Posten->select()) || (!Abfrage.exec(DB_ABFRAGE_AUSGABEN)))
  {
    emit Fehler(tr("Konnte die Tabelle der Buchungen nicht lesen.\n%1").arg(K_Posten->lastError().text()));
    DB.close();
    return false;
  }

  K_Ausgaben->QSqlQueryModel::setQuery(Abfrage);

  K_Kategorien->sort(1,Qt::AscendingOrder);
  K_Posten->sort(1,Qt::AscendingOrder);

  K_Kategorien->setHeaderData(1,Qt::Horizontal,tr("Name der Kategorie"));
  K_Posten->setHeaderData(1,Qt::Horizontal,tr("Datum"));
  K_Posten->setHeaderData(2,Qt::Horizontal,tr("Beschreibung"));
  K_Posten->setHeaderData(3,Qt::Horizontal,trUtf8("Wert in €"));
  K_Posten->setHeaderData(4,Qt::Horizontal,tr("Kategorie"));
  return true;
}
void Datenverwaltung::KategorieAnlegen(const QString &name)
{
  int Zeile=K_Kategorien->rowCount();
  K_Kategorien->insertRow(Zeile);
  K_Kategorien->setData(K_Kategorien->index(Zeile,0),QUuid::createUuid().toString());
  K_Kategorien->setData(K_Kategorien->index(Zeile,1),name);
}
const bool Datenverwaltung::KategorieLoeschen(const int &welche)
{
  QString UUID=K_Kategorien->data(K_Kategorien->index(welche,0)).toString();
  QString Name=K_Kategorien->data(K_Kategorien->index(welche,1)).toString();
  /* Testen ob die Kategroie verwedet wird */
  if(KategorieInBenutzung(UUID))
  {
    emit Warnung(tr("Die Kategorie %1 wird noch verwendet.").arg(Name));
    return false;
  }
  return K_Kategorien->removeRow(welche);
}
bool Datenverwaltung::KategorieInBenutzung(const QString &welche)
{
  QSqlDatabase DB=QSqlDatabase::database(DB_VERBINDUNG,false);
  QSqlQuery Abfrage(DB);
  if(!Abfrage.prepare("select datum from Posten where Kategorie=?;"))
  {
    emit Fehler(tr("Fehler beim Erstellen der Abfrage.\n%1").arg(Abfrage.lastError().text()));
    return true;
  }
  Abfrage.bindValue("?",welche);
  if(!Abfrage.exec())
  {
    emit Fehler(tr("Fehler beim Suchen der Kategorie.\n%1").arg(Abfrage.lastError().text()));
    return true;
  }
  while(Abfrage.next())
    return true;
  return false;
}
void Datenverwaltung::KategorieaenderungSpeichern()
{
  K_Kategorien->submitAll();
  K_Posten->relationModel(4)->select();
}
void Datenverwaltung::PostenMonat(const uint &monat)
{
  K_Filtermonat=monat;
  FilterSetzen();
}
void Datenverwaltung::PostenJahr(const uint &jahr)
{
  K_Filterjahr=jahr;
  FilterSetzen();
}
void Datenverwaltung::FilterSetzen()
{
  QDateTime start;
  QDateTime ende;

  start.setTimeSpec(Qt::UTC);
  ende.setTimeSpec(Qt::UTC);

  start.setDate(QDate(K_Filterjahr,K_Filtermonat,1));
  ende.setDate(QDate(K_Filterjahr,K_Filtermonat,start.date().daysInMonth()));

  K_Posten->setFilter(QString("Datum >%1 and Datum <%2").arg(start.toTime_t()).arg(ende.toTime_t()));
}
void Datenverwaltung::PostenAnlegen(const QDate &datum, const QString &bezeichnung, const double &wert, const QString &kategorie)
{
  QDateTime Zeitstempel;
  Zeitstempel.setTimeSpec(Qt::UTC);
  Zeitstempel.setDate(datum);
  int Zeile=K_Posten->rowCount();
  K_Posten->insertRow(Zeile);
  K_Posten->setData(K_Posten->index(Zeile,0),QUuid::createUuid().toString());
  K_Posten->setData(K_Posten->index(Zeile,1),Zeitstempel.toTime_t());
  K_Posten->setData(K_Posten->index(Zeile,2),bezeichnung);
  K_Posten->setData(K_Posten->index(Zeile,3),wert);
  K_Posten->setData(K_Posten->index(Zeile,4),kategorie);
}
const bool Datenverwaltung::PostenLoeschen(const int &welche)
{
  return K_Posten->removeRow(welche);
}
